<?php
/**
 * +--------------------------------------------------------+
 * @Created by Phpstorm.
 * @Category WebSwooleService.php
 * @Depiction webswoole 方法
 * @Author hwy <429208948@qq.com>
 * @Date 2022/3/4  16:54
 * +--------------------------------------------------------+
 */

namespace App\Services\Swoole;


use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Tymon\JWTAuth\Facades\JWTAuth;
use Tymon\JWTAuth\Providers\Auth\Illuminate;
use Tymon\JWTAuth\Token;

class WebSwooleService
{
    protected $sevr;

    public function __construct()
    {

    }

    public function onOpen($ws, $request)
    {
        $token = $request->get['token'] ?? '';
        $fd         = $request->fd;
        $this->sevr = $ws;
        echo $fd . "_连接成功";
        // SwooleFdService::getInstance()->addData($request->fd, $ws->connection_info($request->fd)['remote_ip']);

        // $token = new Token($token);
        // $jwt = JWTAuth::setToken($token);
        // $JWTAuth = new \Tymon\JWTAuth\JWTAuth(
        //     JWTAuth::manager(),
        //     new Illuminate(Auth::guard($jwt->getClaim('role'))),
        //     JWTAuth::parser()
        // );
        // $user = $JWTAuth->setToken($token)->authenticate(); // info
        // if (empty($user)){
        //     $this->onClose($ws, $ws->fd);
        // }
        //
        // Cache::forever('user_info_' . $fd, $user);
        $ws->push($request->fd, 'hello' . ', welcome\n');
    }

    public function onClose($ws, $fd)
    {
        echo "client:{$fd} is closed\n";
        Cache::forget('user_info_' . $fd);
        // SwooleFdService::getInstance()->updateData($fd);
    }

    /**
     * @param $ws
     * @param $frame
     * @Depiction 当服务器收到来自客户端的数据帧时会回调此函数。
     * @Author hwy <429208948@qq.com>
     * @Date 2022/4/19  14:27
     */
    public function onMessage($ws, $frame)
    {
        /*
            监听WebSocket消息事件
            $frame 是 Swoole\WebSocket\Frame 对象，包含了客户端发来的数据帧信息
            $frame->fd 客户端的 socket id，使用 $server->push 推送数据时需要用到
            $frame->data 数据内容，可以是文本内容也可以是二进制数据，可以通过 opcode 的值来判断
            $frame->opcode WebSocket 的 OpCode 类型，可以参考 WebSocket 协议标准文档
            $frame->finish 表示数据帧是否完整，一个 WebSocket 请求可能会分成多个数据帧进行发送（底层已经实现了自动合并数据帧，现在不用担心接收到的数据帧不完整）
        */

        //
        $this->start_t = microtime(true);
        $data             = json_decode($frame->data, true);
        $route            = $data['route']  ?? '';
        if(empty($route)){
            $ws->push($frame->fd, 'Route Empty');
        }
        //

        /*
         * send 发送数据
         */
        $className = 'App\\Services\\Swoole\\Components\\'.ucfirst($route).'Service';

        if (class_exists($className)) {
            $this->service = new $className;
            $this->service->ws = $ws;
            $this->service->frame = $frame;
            $res = $this->service->handle();
            $res['data']['type'] = $route;

        } else {
            $res = response_error_msg();
        }

        $this->end_t = microtime(true);
        $t           = ($this->end_t - $this->start_t) * 1000 . 'ms';

        echo "{$frame->fd}_Message_: ". $route . '_' . $t . "\n";
        $res = json_encode($res);
        if (in_array($route, ['chat', 'online'])) {
            foreach ($ws->connections as $fd) {
                // 需要先判断是否是正确的websocket连接，否则有可能会push失败
                if ($ws->isEstablished($fd)) {
                    echo 'list:' . $fd . "\n";
                    $ws->push($fd, $res);
                }
            }
        } else {
            $ws->push($frame->fd, $res);
        }

        // var_dump($ws->connection_info($frame->fd));
        //fd绑定客户端传过来的标识uid
        // $ws->bind($frame->fd, $frame->data);

    }

    public function onRequest($request, $response, $ws)
    {
        $scene = $request->get()['message'] ?? 'error';
        swoole_timer_tick(10000, function (int $timer_id) use ($scene, $ws) {
            echo "timer_id #$timer_id, after 10000ms.\n";

            $total = count($ws->connections);
            echo 'total:' . $total . "\n";
            foreach ($ws->connections as $fd) {
                // 需要先判断是否是正确的websocket连接，否则有可能会push失败
                if ($ws->isEstablished($fd)) {
                    echo 'list:' . $fd . "\n";
                    $ws->push($fd, "client is PushMessage " . $scene);
                }
            }
        });

    }

}
